<template>
  <div class="particle-container">
    <canvas
      ref="canvas"
      @mousemove="handleMouseMove"
      @touchmove.prevent="handleTouchMove"
    ></canvas>

    <div class="controls">
      <button @click="toggleAnimation" class="control-button">
        {{ isRunning ? '⏸️ 暂停' : '▶️ 开始' }}
      </button>

      <div class="select-wrapper">
        <select v-model="currentMode" class="mode-select">
          <option v-for="(mode, index) in modes" :key="index" :value="index">
            {{ mode.name }}
          </option>
        </select>
      </div>

      <div class="slider-container">
        <span class="slider-label">粒子数: {{ particleCount }}</span>
        <input
          type="range"
          v-model="particleCount"
          min="10"
          max="1000"
          step="10"
          class="particle-slider"
        >
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'

// 画布和上下文引用
const canvas = ref(null)
const ctx = ref(null)

// 系统状态
const isRunning = ref(true)
const particles = ref([])
const mousePos = ref({ x: null, y: null })
const particleCount = ref(200)
const currentMode = ref(0)

// 定义多种模式
const modes = ref([
  {
    name: '引力场',
    description: '粒子被鼠标吸引',
    color: '#4CAF50',
    behavior: (particle) => {
      // 引力场行为
      if (mousePos.value.x && mousePos.value.y) {
        const dx = mousePos.value.x - particle.x
        const dy = mousePos.value.y - particle.y
        const distance = Math.sqrt(dx * dx + dy * dy)
        const maxDistance = 200

        if (distance < maxDistance) {
          const force = (maxDistance - distance) / maxDistance
          const directionX = (dx / distance) * force * particle.density * 0.6
          const directionY = (dy / distance) * force * particle.density * 0.6

          particle.velocity.x += directionX
          particle.velocity.y += directionY
        }
      }
    }
  },
  {
    name: '排斥场',
    description: '粒子被鼠标排斥',
    color: '#F44336',
    behavior: (particle) => {
      // 排斥场行为
      if (mousePos.value.x && mousePos.value.y) {
        const dx = mousePos.value.x - particle.x
        const dy = mousePos.value.y - particle.y
        const distance = Math.sqrt(dx * dx + dy * dy)
        const maxDistance = 150

        if (distance < maxDistance) {
          const force = (maxDistance - distance) / maxDistance * -1
          const directionX = (dx / distance) * force * particle.density * 0.8
          const directionY = (dy / distance) * force * particle.density * 0.8

          particle.velocity.x += directionX
          particle.velocity.y += directionY
        }
      }
    }
  },
  {
    name: '社交网络',
    description: '粒子形成连接网络',
    color: '#2196F3',
    behavior: (particle) => {
      // 网络行为
      particle.velocity.x *= 0.95
      particle.velocity.y *= 0.95
      particle.color = `rgba(33, 150, 243, ${particle.size / 4})`
    },
    postDraw: () => drawConnections()
  },
  {
    name: '银河漩涡',
    description: '粒子形成彩色漩涡',
    color: '#9C27B0',
    behavior: (particle) => {
      // 漩涡行为
      particle.color = `hsl(${(particle.x / canvas.value.width * 360 + Date.now() * 0.01) % 360}, 80%, 60%)`
      const angle = Math.atan2(particle.y - canvas.value.height/2, particle.x - canvas.value.width/2)
      particle.velocity.x = Math.cos(angle + Math.PI/2) * 0.2
      particle.velocity.y = Math.sin(angle + Math.PI/2) * 0.2
    }
  },
  {
    name: '火焰效果',
    description: '粒子模拟火焰行为',
    color: '#FF9800',
    behavior: (particle) => {
      // 火焰行为
      particle.velocity.y -= 0.1 // 向上飘动
      particle.velocity.x += (Math.random() - 0.5) * 0.2 // 随机左右摆动
      particle.size *= 0.99 // 逐渐变小

      // 如果粒子太小或超出顶部边界，重置它
      if (particle.size < 0.1 || particle.y < 0) {
        resetParticle(particle)
      }

      // 设置颜色基于位置和大小
      const heat = Math.min(1, particle.y / canvas.value.height)
      particle.color = `rgba(255, ${150 + heat * 105}, ${heat * 50}, ${0.5 + heat * 0.5})`
    }
  }
])

// 重置粒子(用于火焰模式)
function resetParticle(particle) {
  particle.x = Math.random() * canvas.value.width
  particle.y = canvas.value.height + Math.random() * 20
  particle.size = Math.random() * 5 + 2
  particle.velocity = {
    x: (Math.random() - 0.5) * 2,
    y: -Math.random() * 3 - 1
  }
}

// 粒子类
class Particle {
  constructor(width, height) {
    this.x = Math.random() * width
    this.y = Math.random() * height
    this.size = Math.random() * 3 + 1
    this.density = Math.random() * 30 + 1
    this.color = modes.value[currentMode.value].color
    this.velocity = {
      x: Math.random() * 2 - 1,
      y: Math.random() * 2 - 1
    }

    // 火焰模式特殊初始化
    if (currentMode.value === 4) {
      resetParticle(this)
    }
  }

  draw() {
    ctx.value.beginPath()
    ctx.value.arc(this.x, this.y, this.size, 0, Math.PI * 2)
    ctx.value.closePath()
    ctx.value.fillStyle = this.color
    ctx.value.fill()
  }

  update() {
    // 边界检查(火焰模式除外)
    if (currentMode.value !== 4) {
      if (this.x < 0 || this.x > canvas.value.width) this.velocity.x *= -0.8
      if (this.y < 0 || this.y > canvas.value.height) this.velocity.y *= -0.8
    }

    // 应用当前模式的行为
    modes.value[currentMode.value].behavior(this)

    // 更新位置
    this.x += this.velocity.x
    this.y += this.velocity.y

    // 绘制粒子
    this.draw()
  }
}

// 初始化粒子系统
function initParticles() {
  particles.value = []
  for (let i = 0; i < particleCount.value; i++) {
    particles.value.push(new Particle(canvas.value.width, canvas.value.height))
  }
}

// 绘制连接线(用于社交网络模式)
function drawConnections() {
  ctx.value.lineWidth = 0.5
  const modeColor = modes.value[currentMode.value].color

  for (let i = 0; i < particles.value.length; i++) {
    for (let j = i + 1; j < particles.value.length; j++) {
      const p1 = particles.value[i]
      const p2 = particles.value[j]
      const dx = p1.x - p2.x
      const dy = p1.y - p2.y
      const distance = Math.sqrt(dx * dx + dy * dy)

      if (distance < 100) {
        const opacity = 1 - distance / 100
        ctx.value.strokeStyle = `${modeColor}${Math.floor(opacity * 255).toString(16).padStart(2, '0')}`
        ctx.value.beginPath()
        ctx.value.moveTo(p1.x, p1.y)
        ctx.value.lineTo(p2.x, p2.y)
        ctx.value.stroke()
      }
    }
  }
}

// 动画循环
let animationId = null
function animate() {
  if (!isRunning.value) return

  // 清空画布，添加渐变背景
  ctx.value.fillStyle = '#111111'
  ctx.value.fillRect(0, 0, canvas.value.width, canvas.value.height)

  // 更新并绘制所有粒子
  particles.value.forEach(particle => particle.update())

  // 执行模式的后期绘制(如连接线)
  if (modes.value[currentMode.value].postDraw) {
    modes.value[currentMode.value].postDraw()
  }

  animationId = requestAnimationFrame(animate)
}

// 处理鼠标移动
function handleMouseMove(event) {
  const rect = canvas.value.getBoundingClientRect()
  mousePos.value = {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top
  }
}

// 处理触摸移动
function handleTouchMove(event) {
  event.preventDefault()
  const rect = canvas.value.getBoundingClientRect()
  mousePos.value = {
    x: event.touches[0].clientX - rect.left,
    y: event.touches[0].clientY - rect.top
  }
}

// 开始/暂停动画
function toggleAnimation() {
  isRunning.value = !isRunning.value
  if (isRunning.value) {
    animate()
  } else {
    cancelAnimationFrame(animationId)
  }
}

// 响应窗口大小变化
function handleResize() {
  canvas.value.width = window.innerWidth
  canvas.value.height = window.innerHeight
  initParticles()
}

// 组件挂载时初始化
onMounted(() => {
  ctx.value = canvas.value.getContext('2d')
  handleResize()
  window.addEventListener('resize', handleResize)
  animate()
})

// 组件卸载时清理
onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  cancelAnimationFrame(animationId)
})

// 监听粒子数量变化
watch(particleCount, (newVal) => {
  initParticles()
})

// 监听模式变化
watch(currentMode, (newMode) => {
  initParticles()
})
</script>

<style lang="scss" scoped>
.particle-container {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background: linear-gradient(135deg, #1a1a1a 0%, #000 100%);

  canvas {
    display: block;
    background: transparent;
    cursor: move;
    transition: opacity 0.3s ease;

    &:hover {
      opacity: 0.95;
    }
  }

  .controls {
    position: absolute;
    bottom: 2rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 1.5rem;
    align-items: center;
    background: rgba(0, 0, 0, 0.7);
    padding: 1rem 2rem;
    border-radius: 2rem;
    backdrop-filter: blur(10px);
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.3);
    z-index: 10;
    border: 1px solid rgba(255, 255, 255, 0.1);

    @media (max-width: 768px) {
      flex-direction: column;
      width: 90%;
      bottom: 1rem;
      gap: 1rem;
      padding: 1rem;
    }

    .control-button {
      padding: 0.6rem 1.2rem;
      background: rgba(255, 255, 255, 0.1);
      color: white;
      border: none;
      border-radius: 0.5rem;
      cursor: pointer;
      font-weight: bold;
      transition: all 0.3s ease;
      display: flex;
      align-items: center;
      gap: 0.5rem;
      font-size: 0.9rem;

      &:hover {
        background: rgba(255, 255, 255, 0.2);
        transform: translateY(-0.1rem);
      }

      &:active {
        transform: translateY(0.1rem);
      }
    }

    .select-wrapper {
      position: relative;

      &::after {
        content: '▼';
        position: absolute;
        top: 50%;
        right: 1rem;
        transform: translateY(-50%);
        color: white;
        font-size: 0.6rem;
        pointer-events: none;
      }
    }

    .mode-select {
      padding: 0.6rem 2rem 0.6rem 1rem;
      background: rgba(255, 255, 255, 0.1);
      color: white;
      border: none;
      border-radius: 0.5rem;
      cursor: pointer;
      appearance: none;
      font-size: 0.9rem;
      transition: all 0.3s ease;
      outline: none;

      &:hover {
        background: rgba(255, 255, 255, 0.2);
      }

      &:focus {
        box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
      }

      option {
        background: #333;
        color: white;
      }
    }

    .slider-container {
      display: flex;
      align-items: center;
      gap: 1rem;
      min-width: 15rem;

      @media (max-width: 768px) {
        width: 100%;
      }

      .slider-label {
        font-size: 0.9rem;
        white-space: nowrap;
        color: rgba(255, 255, 255, 0.8);
      }

      .particle-slider {
        flex-grow: 1;
        height: 0.5rem;
        border-radius: 0.5rem;
        background: rgba(255, 255, 255, 0.1);
        outline: none;
        transition: all 0.3s ease;
        appearance: none;
        cursor: pointer;

        &::-webkit-slider-thumb {
          appearance: none;
          width: 1.2rem;
          height: 1.2rem;
          border-radius: 50%;
          background: v-bind('modes[currentMode].color');
          cursor: pointer;
          transition: all 0.2s ease;
        }

        &::-moz-range-thumb {
          width: 1.2rem;
          height: 1.2rem;
          border-radius: 50%;
          background: v-bind('modes[currentMode].color');
          cursor: pointer;
          transition: all 0.2s ease;
        }

        &:hover {
          &::-webkit-slider-thumb {
            transform: scale(1.1);
            box-shadow: 0 0 0.5rem v-bind('modes[currentMode].color + "80"');
          }
          &::-moz-range-thumb {
            transform: scale(1.1);
            box-shadow: 0 0 0.5rem v-bind('modes[currentMode].color + "80"');
          }
        }
      }
    }
  }
}
</style>
